package com.plian.system.service.im.impl;

import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.fill.FillWrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.plian.Tools.BigDecimalUtil;
import com.plian.Tools.CollectionUtil;
import com.plian.Tools.StringPool;
import com.plian.system.bean.im.FixedInvestmentPlanExcelBean;
import com.plian.system.entity.im.*;
import com.plian.system.mapper.im.*;
import com.plian.system.mybatis.base.BaseServiceImpl;
import com.plian.system.service.im.IFixedInvestmentPlanService;
import com.plian.system.vo.im.FixedInvestmentPlanVO;
import com.plian.system.wrapper.im.FixedInvestmentPlanWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 服务实现类
 *
 * @author
 * @since 2019-09-27
 */
@Slf4j
@Service
@AllArgsConstructor
public class FixedInvestmentPlanServiceImpl extends BaseServiceImpl<FixedInvestmentPlanMapper, FixedInvestmentPlan> implements IFixedInvestmentPlanService {


	private FixedInvestmentPlanWrapper fixedInvestmentPlanWrapper;

	private ExecutionProjectSituationMapper executionProjectSituationMapper;

	private EffectiveInvestmentMapper effectiveInvestmentMapper;

	private BaseInvestmentExecutionMapper baseInvestmentExecutionMapper;

	private ProjectInfoMapper projectInfoMapper;

	private BaseInvestmentPlanMapper baseInvestmentPlanMapper;



	@Override
	public boolean saveOrUpdate(FixedInvestmentPlan fixedInvestmentPlan) {
		return super.saveOrUpdate(fixedInvestmentPlan);
	}

	@Override
	@Transactional(rollbackFor=RuntimeException.class)
	public boolean deleteLogic(List<Long> ids) {
		for (Long id : ids) {
			FixedInvestmentPlan fixedInvestmentPlan = getById(id);
			if (fixedInvestmentPlan == null) {
				return false;
			}
		}
		return super.deleteLogic(ids);
	}

	@Override
	public void write(List<FixedInvestmentPlan> fixedInvestmentPlans, ExcelWriter excelWriter, WriteSheet writeSheet, FillConfig fillConfig) {
		/**
		 * 合计
		 */
		FixedInvestmentPlanExcelBean total = FixedInvestmentPlanExcelBean.builder().build();
		Map<Integer, List<FixedInvestmentPlanVO>> map = fixedInvestmentPlanWrapper.entityToVO(fixedInvestmentPlans)
				.stream().collect(Collectors.groupingBy(FixedInvestmentPlanVO::getProjectCategory));
		for (int i = 1; i < 5; i++) {
			List<FixedInvestmentPlanVO> list = map.get(i);
			FixedInvestmentPlanExcelBean sum = FixedInvestmentPlanExcelBean.builder().build();
			if (CollectionUtil.isNotEmpty(list)) {
				int index = 1;
				for (FixedInvestmentPlanVO vo : list) {
					vo.setIsNewProjectStr(vo.getIsNewProject() == 1 ? "否" : "是");
					vo.setIndex(i + "." + index);
					index++;
					/**
					 * 小计
					 */
					sum.setPlanTotalInvestment(BigDecimalUtil.add(sum.getPlanTotalInvestment(), vo.getPlanTotalInvestment()));
					sum.setCompleteInvestmentLastYear(BigDecimalUtil.add(sum.getCompleteInvestmentLastYear(), vo.getCompleteInvestmentLastYear()));
					sum.setCompleteInvestmentTotal(	BigDecimalUtil.add(sum.getCompleteInvestmentTotal(), vo.getCompleteInvestmentTotal()));
					sum.setPlanInvestmentTotal(BigDecimalUtil.add(sum.getPlanInvestmentTotal(), vo.getPlanInvestmentTotal()));
				}
				sum.setIndex(i + "." + index);
				/**
				 * 数据填充
				 */
				switch (i){
					case 1:
						excelWriter.fill(toMap("one", sum), fillConfig, writeSheet);
						excelWriter.fill(new FillWrapper("one", list), fillConfig, writeSheet);
						break;
					case 2:
						excelWriter.fill(toMap("two", sum), fillConfig, writeSheet);
						excelWriter.fill(new FillWrapper("two", list), fillConfig, writeSheet);
						break;
					case 3:
						excelWriter.fill(toMap("three", sum), fillConfig, writeSheet);
						excelWriter.fill(new FillWrapper("three", list), fillConfig, writeSheet);
						break;
					case 4:
						excelWriter.fill(toMap("four", sum), fillConfig, writeSheet);
						excelWriter.fill(new FillWrapper("four", list), fillConfig, writeSheet);
						break;
					default:
						break;
				}
			}


			/**
			 * 总计
			 */
			total.setPlanTotalInvestment(BigDecimalUtil.add(sum.getPlanTotalInvestment(), total.getPlanTotalInvestment()));
			total.setCompleteInvestmentLastYear(BigDecimalUtil.add(sum.getCompleteInvestmentLastYear(), total.getCompleteInvestmentLastYear()));
			total.setCompleteInvestmentTotal(BigDecimalUtil.add(sum.getCompleteInvestmentTotal(), total.getCompleteInvestmentTotal()));
			total.setPlanInvestmentTotal(BigDecimalUtil.add(sum.getPlanInvestmentTotal(), total.getPlanInvestmentTotal()));

		}

		excelWriter.fill(toMap("five", total), fillConfig, writeSheet);
	}

	@Override
	public boolean deleteByBaseId(Long baseInvestmentPlanId) {
		List<FixedInvestmentPlan> fixedInvestmentPlans = list(new LambdaQueryWrapper<FixedInvestmentPlan>()
				.eq(FixedInvestmentPlan::getBaseInvestmentPlanId, baseInvestmentPlanId));
		if (CollectionUtil.isNotEmpty(fixedInvestmentPlans)){
			return deleteLogic(fixedInvestmentPlans.stream().map(FixedInvestmentPlan::getId).collect(Collectors.toList()));
		}
		return true;
	}

	@Override
	public boolean deleteByParentId(List<Long> ids) {
		LambdaQueryWrapper<FixedInvestmentPlan> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.in(FixedInvestmentPlan::getBaseInvestmentPlanId, ids);
		List<FixedInvestmentPlan> fixedInvestmentPlans = list(queryWrapper);
		if (CollectionUtil.isNotEmpty(fixedInvestmentPlans)){
			return deleteLogic(fixedInvestmentPlans.stream().map(FixedInvestmentPlan::getId).collect(Collectors.toList()));
		}
		return true;
	}

	@Override
	public String checkMsg(List<FixedInvestmentPlan> fixedInvestmentPlanList,int year) {
		StringBuilder msg=new StringBuilder();
		List<Long> projectIds = fixedInvestmentPlanList.stream().map(FixedInvestmentPlan::getProjectId).filter(m -> Optional.ofNullable(m).isPresent()).collect(Collectors.toList());

		List<ProjectInfo> projectInfos = projectInfoMapper.selectBatchIds(projectIds);

		//去年投资项目情况
		List<ExecutionProjectSituation> executionProjectSituations = executionProjectSituationMapper.selectList(Wrappers.<ExecutionProjectSituation>lambdaQuery().in(ExecutionProjectSituation::getProjectId, projectIds));
		List<EffectiveInvestment> effectiveInvestments = new ArrayList<>();
		List<BaseInvestmentExecution> investmentExecutions = new ArrayList<>();
		if (CollectionUtil.isNotEmpty(executionProjectSituations)){
			effectiveInvestments = effectiveInvestmentMapper.selectBatchIds(executionProjectSituations.stream().map(ExecutionProjectSituation::getEffectiveInvestmentId).collect(Collectors.toList()));
			if (CollectionUtil.isNotEmpty(effectiveInvestments)){
				investmentExecutions = baseInvestmentExecutionMapper.selectBatchIds(effectiveInvestments.stream().map(EffectiveInvestment::getBaseInvestmentExecutionId).collect(Collectors.toList()));
			}
		}

		for(FixedInvestmentPlan fixedInvestmentPlan:fixedInvestmentPlanList) {
			StringBuilder str=new StringBuilder();
			String projectName=fixedInvestmentPlan.getProjectName();
			Long projectId = fixedInvestmentPlan.getProjectId();
			//是否续建项目
			Optional<ProjectInfo> projectOptional = projectInfos.stream().filter(m -> projectId.equals(m.getId())).findFirst();
			if (projectOptional.isPresent()){
				ProjectInfo projectInfo = projectOptional.get();
				if (Optional.ofNullable(projectInfo.getProjectStatus()).isPresent() && projectInfo.getProjectStatus() == 1) {
					//上年度 + 投资额 = 累计总额
					//去年投资执行情况
					BigDecimal lastCount = BigDecimal.ZERO;
					if (CollectionUtil.isNotEmpty(executionProjectSituations)){
						List<ExecutionProjectSituation> projectSituations = executionProjectSituations.stream().filter(m -> projectId.equals(m.getProjectId())).collect(Collectors.toList());
						if (CollectionUtil.isNotEmpty(projectSituations)){
							List<Long> executionIds = projectSituations.stream().map(ExecutionProjectSituation::getEffectiveInvestmentId).collect(Collectors.toList());
							List<EffectiveInvestment> investmentList = effectiveInvestments.stream().filter(m -> executionIds.contains(m.getId())).collect(Collectors.toList());
							if (CollectionUtil.isNotEmpty(investmentList)){
								List<Long> baseIds = investmentList.stream().map(EffectiveInvestment::getBaseInvestmentExecutionId).collect(Collectors.toList());
								Optional<BaseInvestmentExecution> max = investmentExecutions.stream().filter(m -> baseIds.contains(m.getId())).max(Comparator.comparing(BaseInvestmentExecution::getFilingMonth));
								if (max.isPresent()){
									Optional<EffectiveInvestment> effectiveInvestmentOptional = investmentList.stream().filter(m -> max.get().getId().equals(m.getBaseInvestmentExecutionId())).findFirst();
									if (effectiveInvestmentOptional.isPresent()){
										Optional<ExecutionProjectSituation> executionOptional = projectSituations.stream().filter(m -> effectiveInvestmentOptional.get().getId().equals(m.getEffectiveInvestmentId())).max(Comparator.comparing(ExecutionProjectSituation::getCreateTime));
										if (executionOptional.isPresent()){
											ExecutionProjectSituation executionProjectSituation = executionOptional.get();
											//去年 至上月底完成 + 本月完成投资
//											lastCount = executionProjectSituation.getLastCompleteInvestment().add(executionProjectSituation.getCompleteInvestment());
										}
									}
								}
							}
						}
					}

					//已完成投资 其中：上年度实际投资
					BigDecimal completeInvestmentLastYear = fixedInvestmentPlan.getCompleteInvestmentLastYear();
					if(Optional.ofNullable(completeInvestmentLastYear).isPresent() && lastCount.compareTo(completeInvestmentLastYear)!=0){
//						str.append("本年计划完成投资  本年已完成投资 其中：上年度实际投资 ≠ 上年度累计完成投资额").append(StringPool.SEMICOLON);
					}
					//是否本年新增项目为否
					if (Optional.ofNullable(fixedInvestmentPlan.getIsNewProject()).isPresent() && fixedInvestmentPlan.getIsNewProject() != 1){
						str.append("是否本年新增项目应该为否").append(StringPool.SEMICOLON);
					}
					if (str.toString().length()>0){
                        msg.append(str);
                    }

				}
			}
			if(str.toString().length()>0){
				str.insert(0,projectName+StringPool.COLON);
			}
			if(str.toString().length()>0){
				msg.append(str);
			}
		}

		return msg.toString();
	}

	private Map<String, Object> toMap(String str, FixedInvestmentPlanExcelBean bean){
		Map<String, Object> map = new HashMap<>(16);
		map.put(str + "FixedIndex", bean.getIndex());
		map.put(str + "PlanTotalInvestment", bean.getPlanTotalInvestment());
		map.put(str + "CompleteInvestmentLastYear", bean.getCompleteInvestmentLastYear());
		map.put(str + "CompleteInvestmentTotal", bean.getCompleteInvestmentTotal());
		map.put(str + "PlanInvestmentTotal", bean.getPlanInvestmentTotal());
		return map;
	}
}
